#include "lru_replacer.h"

LRUReplacer::LRUReplacer(size_t num_pages) { max_size_ = num_pages; }

LRUReplacer::~LRUReplacer() = default;

/**
 * @brief 使用LRU策略删除一个victim frame，这个函数能得到frame_id
 * @param[out] frame_id id of frame that was removed, nullptr if no victim was found
 * @return true if a victim frame was found, false otherwise
 */
bool LRUReplacer::Victim(frame_id_t *frame_id) {
    // C++17 std::scoped_lock
    // 它能够避免死锁发生，其构造函数能够自动进行上锁操作，析构函数会对互斥量进行解锁操作，保证线程安全。
    std::scoped_lock lock{latch_};

    // Todo:
    //  利用lru_replacer中的LRUlist_,LRUHash_实现LRU策略
    //  选择合适的frame指定为淘汰页面,赋值给*frame_id
    if(LRUlist_.empty() == 0)// 检查LRU列表是否为空
    {
	    *frame_id = LRUlist_.back();// 如果不为空，将最后一个frame_id设置到frame_id指针中
	    LRUlist_.pop_back();// 弹出LRU列表的最后一个frame_id
	    return true;// 返回true表示找到了victim frame
    }
    else
    {
        return false;// 如果LRU列表为空，返回false表示未找到victim frame
    }
}

/**
 * @brief 固定一个frame, 表明它不应该成为victim（即在replacer中移除该frame_id）
 * @param frame_id the id of the frame to pin
 */
void LRUReplacer::Pin(frame_id_t frame_id) {
    std::scoped_lock lock{latch_};
    // Todo:
    // 固定指定id的frame
    // 在数据结构中移除该frame
    LRUlist_.remove(frame_id);// 使用std::scoped_lock进行线程安全的锁定
}

/**
 * 取消固定一个frame, 表明它可以成为victim（即将该frame_id添加到replacer）
 * @param frame_id the id of the frame to unpin
 */
void LRUReplacer::Unpin(frame_id_t frame_id) {
    // Todo:
    //  支持并发锁
    //  选择一个frame取消固定
    int flag = 1; 
    latch_.lock();// 获取锁（这里是使用锁对象latch_，但是没有显式地调用lock函数）
    std::list<frame_id_t>::iterator it = LRUlist_.begin();// 使用迭代器遍历LRU列表
    while(it != LRUlist_.end())// 遍历列表，查找要取消固定的frame_id
    {
	    if(*it == frame_id)
        {
		    flag = 0;
		    break;
	    }
	    ++it;
    }
    if(flag)// 如果flag为1，表示frame_id不在LRU列表中，将其添加到列表头部
    {
        LRUlist_.push_front(frame_id);
    }
    latch_.unlock();// 释放锁
}

/** @return replacer中能够victim的数量 */
size_t LRUReplacer::Size() {
    // Todo:
    // 改写return size
    return LRUlist_.size();// 返回LRU列表中的frame数量
}
